package service

import (
	"context"
	"errors"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"insighttracking/common/utils"
	"insighttracking/query/bo"
	"insighttracking/query/dao"
	"insighttracking/query/model"
	"sync"
	"time"
)

type _spuShelfGridInventoryService struct{}

var lock3 sync.Mutex
var lock4 sync.Mutex

func (s _spuShelfGridInventoryService) IncrGridInventoryApi(ctx context.Context, tx *dao.QueryTx, enterpriseId int64, shelfID, spuID, supplierID int64, expirationDate string, batchNumber string, changeCount decimal.Decimal) (lastInventoryCount decimal.Decimal, err error) {
	lock3.Lock()
	defer lock3.Unlock()
	var expirationDateTime time.Time
	if expirationDate != "" {
		expirationDateTime = utils.DateStrToTime(expirationDate)
	} else {
		spu, _ := dao.SpuEntity.WithContext(ctx).Where(dao.SpuEntity.ID.Eq(spuID)).First()
		if spu.Period != 0 {
			expirationDateTime = time.Now().AddDate(0, 0, int(spu.Period))
		} else {
			// 保质期默认一个月
			expirationDateTime = time.Now().AddDate(0, 0, 30)
		}
	}

	inventoryEntity, err := dao.SpuShelfGridInventoryEntity.WithContext(ctx).Where(
		dao.SpuShelfGridInventoryEntity.EnterpriseID.Eq(enterpriseId),
		dao.SpuShelfGridInventoryEntity.ShelfID.Eq(shelfID),
		dao.SpuShelfGridInventoryEntity.SpuID.Eq(spuID),
		dao.SpuShelfGridInventoryEntity.BatchNumber.Eq(batchNumber),
	).First()
	if errors.Is(err, gorm.ErrRecordNotFound) {
		// 创建
		lastInventoryCount = changeCount
		if err = tx.SpuShelfGridInventoryEntity.WithContext(ctx).Create(&model.SpuShelfGridInventoryEntity{
			EnterpriseID:   enterpriseId,
			SpuID:          spuID,       // 商品id,关联打牌spu表主键id
			ShelfID:        shelfID,     // 货架ID
			BatchNumber:    batchNumber, // 批次号
			SupplierID:     supplierID,  // 供应商ID
			InventoryCount: changeCount, // 当前仓库库存数量
			ExpirationDate: expirationDateTime,
		}); err != nil {
			return
		}
	} else {
		// 更新
		lastInventoryCount = inventoryEntity.InventoryCount.Add(changeCount)
		if _, err = tx.SpuShelfGridInventoryEntity.WithContext(ctx).Where(dao.SpuShelfGridInventoryEntity.ID.Eq(inventoryEntity.ID)).UpdateSimple(
			dao.SpuShelfGridInventoryEntity.InventoryCount.Value(lastInventoryCount),
		); err != nil {
			return
		}
	}
	return
}

func (s _spuShelfGridInventoryService) ReduceInventoryApi(ctx context.Context, tx *dao.QueryTx, enterpriseId int64, shelfID, spuID int64, batchNumber string, changeCount decimal.Decimal) (lastInventoryCount decimal.Decimal, err error) {
	lock4.Lock()
	defer lock4.Unlock()
	inventoryEntity, err := dao.SpuShelfGridInventoryEntity.WithContext(ctx).Where(
		dao.SpuShelfGridInventoryEntity.EnterpriseID.Eq(enterpriseId),
		dao.SpuShelfGridInventoryEntity.ShelfID.Eq(shelfID),
		dao.SpuShelfGridInventoryEntity.SpuID.Eq(spuID),
		dao.SpuShelfGridInventoryEntity.BatchNumber.Eq(batchNumber),
	).First()
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return lastInventoryCount, errors.New("当前仓库没有该商品")
	}
	if inventoryEntity.InventoryCount.LessThan(changeCount) {
		return lastInventoryCount, errors.New("库存不足")
	}
	// 更新
	lastInventoryCount = inventoryEntity.InventoryCount.Sub(changeCount)
	if _, err = tx.SpuShelfGridInventoryEntity.WithContext(ctx).Where(dao.SpuShelfGridInventoryEntity.ID.Eq(inventoryEntity.ID)).UpdateSimple(
		dao.SpuShelfGridInventoryEntity.InventoryCount.Value(lastInventoryCount),
	); err != nil {
		return
	}
	return
}

func (s _spuShelfGridInventoryService) GetUsedGridBySpuApi(ctx context.Context, enterpriseId int64, spuId int64) (gridIDs []int64, err error) {
	gridIDs = make([]int64, 0)
	err = dao.SpuShelfGridInventoryEntity.WithContext(ctx).Where(
		dao.SpuShelfGridInventoryEntity.EnterpriseID.Eq(enterpriseId),
		dao.SpuShelfGridInventoryEntity.SpuID.Eq(spuId)).Pluck(dao.SpuShelfGridInventoryEntity.ShelfGridID, &gridIDs)
	return
}

func (s _spuShelfGridInventoryService) GetBySpuIDApi(ctx context.Context, enterpriseId int64, spuId int64, batchNumber string) (resp []*model.SpuShelfGridInventoryEntity, err error) {
	tx := dao.SpuShelfGridInventoryEntity.WithContext(ctx).Where(
		dao.SpuShelfGridInventoryEntity.EnterpriseID.Eq(enterpriseId),
		dao.SpuShelfGridInventoryEntity.SpuID.Eq(spuId))
	if batchNumber != "" {
		tx.Where(dao.SpuShelfGridInventoryEntity.BatchNumber.Eq(batchNumber))
	}
	return tx.Find()
}

func (s _spuShelfGridInventoryService) GetAvailableBatchNumberApi(ctx context.Context, shelfID int64, spuId int64) (resp []*bo.InventoryBatchNumber, err error) {
	err = dao.SpuShelfGridInventoryEntity.WithContext(ctx).
		Select(dao.SpuShelfGridInventoryEntity.BatchNumber,
			dao.SpuShelfGridInventoryEntity.CreatedAt,
			dao.SpuShelfGridInventoryEntity.InventoryCount,
			dao.SupplierEntity.Name.As("SupplierName"),
		).
		LeftJoin(dao.SupplierEntity, dao.SupplierEntity.ID.EqCol(dao.SpuShelfGridInventoryEntity.SupplierID)).
		Where(
			dao.SpuShelfGridInventoryEntity.ShelfID.Eq(shelfID),
			dao.SpuShelfGridInventoryEntity.SpuID.Eq(spuId)).Scan(&resp)
	return
}

func (s _spuShelfGridInventoryService) GetDefaultBatchNumberApi(ctx context.Context, spuId int64) (resp bo.InventoryBatchNumber, err error) {
	err = dao.SpuShelfGridInventoryEntity.WithContext(ctx).
		Select(dao.SpuShelfGridInventoryEntity.BatchNumber,
			dao.SpuShelfGridInventoryEntity.CreatedAt,
			dao.SpuShelfGridInventoryEntity.InventoryCount,
			dao.SupplierEntity.Name.As("SupplierName"),
			dao.SpuEntity.Name.As("SpuName"),
			dao.ShelfEntity.Code.As("ShelfCode"),
		).
		LeftJoin(dao.SupplierEntity, dao.SupplierEntity.ID.EqCol(dao.SpuShelfGridInventoryEntity.SupplierID)).
		LeftJoin(dao.SpuEntity, dao.SpuEntity.ID.EqCol(dao.SpuShelfGridInventoryEntity.SpuID)).
		LeftJoin(dao.ShelfEntity, dao.ShelfEntity.ID.EqCol(dao.SpuShelfGridInventoryEntity.ShelfID)).
		Where(
			dao.SpuShelfGridInventoryEntity.SpuID.Eq(spuId)).Order(dao.SpuShelfGridInventoryEntity.ExpirationDate.Asc()).Scan(&resp)
	return
}

func (s _spuShelfGridInventoryService) GetInventoryApi(ctx context.Context, enterpriseId int64, spuId int64) (resp []*bo.GetInventoryResp, err error) {
	err = dao.SpuShelfGridInventoryEntity.WithContext(ctx).
		Select(
			dao.SpuShelfGridInventoryEntity.ALL,
			dao.WarehouseAreaEntity.Name.As("WarehouseAreaName"),
			dao.WarehouseEntity.Name.As("WarehouseName"),
			dao.ShelfEntity.Name.As("ShelfName")).
		LeftJoin(dao.ShelfEntity, dao.ShelfEntity.ID.EqCol(dao.SpuShelfGridInventoryEntity.ShelfID)).
		LeftJoin(dao.WarehouseAreaEntity, dao.WarehouseAreaEntity.ID.EqCol(dao.ShelfEntity.WarehouseAreaID)).
		LeftJoin(dao.WarehouseEntity, dao.WarehouseEntity.ID.EqCol(dao.ShelfEntity.WarehouseID)).
		Where(
			dao.SpuShelfGridInventoryEntity.EnterpriseID.Eq(enterpriseId),
			dao.SpuShelfGridInventoryEntity.SpuID.Eq(spuId)).Scan(&resp)
	return
}

var SpuShelfGridInventoryService = new(_spuShelfGridInventoryService)
